import 'dart:convert';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:im_app/im/pojo/Enums.dart';
import 'package:im_app/im/service/ImDepartmentService.dart';
import 'package:im_app/im/service/LoginService.dart';
import 'package:im_app/im/socket/service/RpcPullDataService.dart';
import 'package:im_app/im/socket/ImWebSocketIsolate.dart';
import 'package:im_app/im/socket/dto/business/Login.dart';
import 'package:im_app/im/socket/dto/business/PullData.dart';
import 'package:im_app/im/socket/dto/business/RpcData.dart';
import 'package:im_app/im/util/DbUtil.dart';
import 'package:im_app/im/util/ImSingleton.dart';
import 'package:logger/logger.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';

void main()  {
  test("test websocket login", () async {
    ImWebSocketIsolate imWebSocket = new ImWebSocketIsolate('ws://127.0.0.1:9290/imWebsocket');
    await imWebSocket.start();
    ImSingleton.getInstance()?.imWebSocket = imWebSocket;
    var logger = Logger();
    logger.i("websocket run");
    LoginReq loginReq = LoginReq(userId: "test00100", password: "123456", machineCode: "demo",
        tenantCode: "0000", terminalType: "android");
    Map<String, String> extDataMap = {"localSeq": "1"};
    RpcData rpcData = new RpcData("login", 1, 0, extDataMap, loginReq);
    logger.i("login json: " + loginReq.toJson().toString());
    RpcData? resultRpcData = await ImSingleton.getInstance()?.imWebSocket.sendData(rpcData, LoginResp.fromJson, 60);
    logger.i("login success result : " + jsonEncode(resultRpcData?.data));
    var duration = const Duration(seconds: 10);
    logger.i('Start sleeping');
    sleep(duration);
    imWebSocket.close();
  });

  test("test websocket pull departments", () async {
    sqfliteFfiInit();
    databaseFactory = databaseFactoryFfi;
    Database database = await DbUtil.connect("imtest.db");
    ImSingleton.getInstance()?.dataBase = database;

    ImWebSocketIsolate imWebSocket = new ImWebSocketIsolate('ws://127.0.0.1:9290/imWebsocket');
    await imWebSocket.start();
    ImSingleton.getInstance()?.imWebSocket = imWebSocket;
    var logger = Logger();
    logger.i("websocket run");

    String userId = "test00100";
    LoginReq loginReq = LoginReq(userId: "test00100", password: "123456", machineCode: "demo",
        tenantCode: "0000", terminalType: "android");
    logger.i("login json: " + loginReq.toJson().toString());
    LoginService loginService = LoginService();
    LoginResp? loginResp = await loginService.login(loginReq, LoginType.password);
    logger.i("login success result : " + jsonEncode(loginResp));

    DepartmentInfoListReq departmentInfoListReq = new DepartmentInfoListReq();
    departmentInfoListReq.pageSize = 1000;
    var pullDataService = new RpcPullDataService();
    DepartmentInfoListItem? departmentInfoListItem = await pullDataService.pullDepartmentInfoList(departmentInfoListReq);
    logger.i("departmentInfoList resp json: " + jsonEncode(departmentInfoListItem));

    var departmentService = ImDepartmentService();
    departmentService.saveOrUpdates(userId, departmentInfoListItem.departmentInfoItemList);

    var duration = const Duration(seconds: 10);
    logger.i('Start sleeping');
    sleep(duration);
    imWebSocket.close();
    database.close();
  }, timeout: Timeout.factor(20));

  test("test websocket pull userInfo", () async {
    ImWebSocketIsolate imWebSocket = new ImWebSocketIsolate('ws://127.0.0.1:9290/imWebsocket');
    await imWebSocket.start();
    ImSingleton.getInstance().imWebSocket = imWebSocket;
    var logger = Logger();
    logger.i("websocket run");
    LoginReq loginReq = LoginReq(userId: "test00100", password: "123456", machineCode: "demo",
        tenantCode: "0000", terminalType: "android");
    RpcData rpcData = RpcData.data("login", loginReq,  "1");
    logger.i("login json: " + loginReq.toJson().toString());
    RpcData? resultRpcData = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData, LoginResp.fromJson, 50);
    logger.i("login success result : " + jsonEncode(resultRpcData?.data));

    int pageSize = 100;
    int i = 0;
    UserInfoListReq userInfoListReq = new UserInfoListReq();
    userInfoListReq.pageSize = pageSize;
    userInfoListReq.isLatestChange = false;
    RpcData rpcData2 = RpcData.data("pullUsers", userInfoListReq, "125");
    RpcData? resultRpcData2 = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData2,
        UserInfoListItem.fromJson, 60);
    logger.i("userInfo resp json: " + jsonEncode(resultRpcData2?.data));
    Set<String> userIds = Set();
    if(resultRpcData2?.data is UserInfoListItem) {
      UserInfoListItem userInfoListItem = resultRpcData2?.data as UserInfoListItem;
      userIds.addAll(userInfoListItem.userInfoItemList.map((e) => e.userId).toSet());
      while (userInfoListItem.userInfoItemList.length == pageSize) {
        List<String> userIdList = userInfoListItem.userInfoItemList.map((e) => e.userId).toList();
        userIdList.sort((left, right)=> right.compareTo(left));
        String startUserId = userIdList[0];
        userInfoListReq.startUserId = startUserId;
        int ss = 125 + i++;
        RpcData rpcData2 = RpcData.data("pullUsers", userInfoListReq, "$ss");
        logger.i("userInfo req json: " + jsonEncode(rpcData2?.data));
        RpcData? resultRpcData2 = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData2,
            UserInfoListItem.fromJson, 50);
        logger.i("userInfo resp json: " + jsonEncode(resultRpcData2?.data));
        userInfoListItem = resultRpcData2?.data as UserInfoListItem;
        userIds.addAll(userInfoListItem.userInfoItemList.map((e) => e.userId).toSet());
      }
    }
    logger.i("user size : ${userIds.length}");
    var duration = const Duration(seconds: 10);
    logger.i('Start sleeping');
    sleep(duration);
    imWebSocket.close();
  }, timeout: Timeout.factor(3));

  test("test websocket pull message group", () async {
    ImWebSocketIsolate imWebSocket = new ImWebSocketIsolate('ws://127.0.0.1:9290/imWebsocket');
    await imWebSocket.start();
    ImSingleton.getInstance()?.imWebSocket = imWebSocket;
    var logger = Logger();
    logger.i("websocket run");
    LoginReq loginReq = LoginReq(userId: "test00100", password: "123456", machineCode: "demo",
        tenantCode: "0000", terminalType: "android");
    Map<String, String> extDataMap = {"localSeq": "1"};
    RpcData rpcData = new RpcData("login", 1, 0, extDataMap, loginReq);
    logger.i("login json: " + loginReq.toJson().toString());
    RpcData? resultRpcData = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData, LoginResp.fromJson, 50);
    logger.i("login success result : " + jsonEncode(resultRpcData?.data));

    int i = 0;
    int pageSize = 500;
    var sessionPullReq = new SessionPullReq(pageSize);
    RpcData rpcData2 = RpcData.data("pullMessageGroups", sessionPullReq, "225");
    RpcData? resultRpcData2 = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData2, SessionItemList
        .fromJson, 50);
    logger.i("message group resp json: " + jsonEncode(resultRpcData2?.data));
    if(resultRpcData2?.data is SessionItemList) {
      var sessionItemList = resultRpcData2?.data as SessionItemList;
      // logger.i("message group success result : " + jsonEncode(groupInfoListItem));
      for(var element in sessionItemList.sessionItemList) {
        MessagePullP2pReq messagePullP2pReq = MessagePullP2pReq(TerminalType.android, 1000);
        messagePullP2pReq.groupId = element.groupId;
        messagePullP2pReq.fromUserId = element.userId;

        int seq = 325 + i++;
        RpcData rpcData3 = RpcData.data("pullP2p", messagePullP2pReq, "$seq");
        RpcData? resultRpcData3 = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData3,
            MessageListItem.fromJson, 60);
        // logger.i("message group resp json: " + jsonEncode(resultRpcData3?.data));
      }
    }
    var duration = const Duration(seconds: 10);
    logger.i('Start sleeping');
    sleep(duration);
    imWebSocket.close();
  }, timeout: Timeout.factor(3));

  test("test websocket pull group info", () async {
    ImWebSocketIsolate imWebSocket = new ImWebSocketIsolate('ws://127.0.0.1:9290/imWebsocket');
    await imWebSocket.start();
    ImSingleton.getInstance()?.imWebSocket = imWebSocket;
    var logger = Logger();
    logger.i("websocket run");
    LoginReq loginReq = LoginReq(userId: "test00100", password: "123456", machineCode: "demo",
        tenantCode: "0000", terminalType: "android");
    Map<String, String> extDataMap = {"localSeq": "1"};
    RpcData rpcData = new RpcData("login", 1, 0, extDataMap, loginReq);
    logger.i("login json: " + loginReq.toJson().toString());
    RpcData? resultRpcData = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData, LoginResp.fromJson, 50);
    logger.i("login success result : " + jsonEncode(resultRpcData?.data));

    GroupInfoListReq groupInfoListReq = new GroupInfoListReq(GroupType.chat);
    RpcData rpcData2 = RpcData.data("pullGroups", groupInfoListReq, "225");
    RpcData? resultRpcData2 = await ImSingleton.getInstance()?.imWebSocket?.sendData(rpcData2,
        GroupInfoListItem.fromJson, 50);
    logger.i("groupInfo resp json: " + jsonEncode(resultRpcData2?.data));
    Set<String> groupIds = Set();
    if(resultRpcData2?.data is GroupInfoListItem) {
      GroupInfoListItem groupInfoListItem = resultRpcData2?.data as GroupInfoListItem;
      groupIds.addAll(groupInfoListItem.groupInfoItemList.map((e) => e.groupId).toSet());
    }
    logger.i("group size : ${groupIds.length}");
    var duration = const Duration(seconds: 10);
    logger.i('Start sleeping');
    sleep(duration);
    imWebSocket.close();
  }, timeout: Timeout.factor(3));



}
